/**
 * Created by sjg on 17/9/1.
 */
var ItbUserModel = require('../../../common/mysql/mapping/ItbUserModel');
var TgSearchTagModel = require('../../../common/mysql/mapping/TgSearchTagModel');
var ItbNotificationModel = require('../../../common/mysql/mapping/ItbNotificationModel');
var TgTypeModel = require('../../../common/mysql/mapping/TgTypeModel');
var TgSpecialTopicModel = require('../../../common/mysql/mapping/TgSpecialTopicModel');
var TgKeywordModel = require('../../../common/mysql/mapping/TgKeywordModel');
var TgOutlineModel = require('../../../common/mysql/mapping/TgOutlineModel');
var TgDesignDocModel = require('../../../common/mysql/mapping/TgDesignDocModel');
var TgUserDocModel = require('../../../common/mysql/mapping/TgUserDocModel');
var TgUserPageModel = require('../../../common/mysql/mapping/TgUserPageModel');
var TgUserPcModel = require('../../../common/mysql/mapping/TgUserPcModel');
var TgDesignPcModel = require('../../../common/mysql/mapping/TgDesignPcModel');
var ItbBuyTmplModel = require('../../../common/mysql/mapping/ItbBuyTmplModel');
var ItbTmplPriceModel = require('../../../common/mysql/mapping/ItbTmplPriceModel');
var ItbTemplateModel = require('../../../common/mysql/mapping/ItbTemplateModel');
var ItbItemsModel = require('../../../common/mysql/mapping/ItbItemsModel');
var ItbDocTypeModel = require('../../../common/mysql/mapping/ItbDocTypeModel');
var ItbSceneModel = require('../../../common/mysql/mapping/ItbSceneModel');
var ItbMemberModel = require('../../../common/mysql/mapping/ItbMemberModel');
var ItbTmplPageModel = require('../../../common/mysql/mapping/ItbTmplPageModel');
var TgDesignPageModel = require('../../../common/mysql/mapping/TgDesignPageModel');
var ItbActivityRModel = require('../../../common/mysql/mapping/ItbActivityRModel');
var ItbActivityModel = require('../../../common/mysql/mapping/ItbActivityModel');
var ItbFeedBackModel = require('../../../common/mysql/mapping/ItbFeedbackModel');
var VideoDesignDocModel = require('../../../common/mysql/mapping/VideoDesignDocModel');
var VideoUserDocModel = require('../../../common/mysql/mapping/VideoUserDocModel');

var luaSearchUtil = require('./luaSearchUtil');
var tg3Util = require('./tg3Util');
var ApiComUtil = require('./CommonUtil');
var CommonUtil = require('../../../common/util/CommonUtil');
var SJGNode = require('./../../sjg/common/tg/SJGNode');
var SJGTG = require('./../../sjg/common/tg/SJGTG');
var SJGTGV3 = require('./../../sjg/common/tg3/SJGTGV3');
var SJGNodeV3 = require('./../../sjg/common/tg3/SJGNodeV3');
var GroupObj = require('./../../sjg/kernel/obj/GroupObj');
var FColor = require('./../../sjg/kernel/color/FColor');
var GlobalData = require('./../../sjg/z/GlobalData');
var SJGPage = require('./../../sjg/kernel/cont/SJGPage');
var GCJ_CLASS_TYPE = require('./../../sjg/common/GCJ_CLASS_TYPE');

var CONFIG = require('../../../common/config');
var CODE = require('../../../common/code');
var superagent = require('superagent');
var async = require( 'async'); // 同步控制
var rpcFunc=require('../../routes/rpcSrv/rpcFunc.js');



//------------------------------------------------------------------
// lua search的redis1的设置
var redis = require("redis");
var redisClient = redis.createClient({
    host:CONFIG.LAB_SEARCH_REDIS_SERVER_DOMAIN,
    auth_pass:CONFIG.LAB_SEARCH_REDIS_SERVER_PASSWORD,
    port:CONFIG.LAB_SEARCH_REDIS_SERVER_PORT,
    db:CONFIG.LAB_SEARCH_REDIS_SERVER_DB_NUMBER,
    ttl:CONFIG.LAB_SEARCH_REDIS_SERVER_TTL,
});
var Scripto = require('redis-scripto');
var scriptManager = new Scripto(redisClient);
scriptManager.loadFromDir(__dirname+'/../../lua3');
scriptManager.run('common', [], [], function(err, result) {
    // 预执行公共函数
    console.log(err);
});



var labUtil = (function(){

    function labUtil (){
    }
    // 返回json
    labUtil.ret_func_json = function (success, msg, data, res){
        var obj = {
            success: success,
            msg: msg,
            data: data
        };
        // 返回
        res.set('Content-Type', 'application/json');
        res.json(obj);
    };

    //-----------------------------------------------------------

    /**
     * 获取实验室搜集信息答案选项列表
     * @param callback 回调
     *          error: 错误
     *          data: {
     *              '1' : [], // 行业
     *              '3' : [], // 风格
     *              '4' : [], // 颜色
     *          }
     * */
    labUtil.getLabQuestionsOptions = function(callback) {

        var keywordModel = new TgKeywordModel({
            types : "1,3,4"
        });
        var obj = {
            "1" : [
                {"id": 1, "name": "互联网", "thumb": "", "type": 1},
                {"id": 2, "name": "电商", "thumb": "", "type": 1},
                {"id": 3, "name": "科技", "thumb": "", "type": 1},
                {"id": 4, "name": "交通", "thumb": "", "type": 1},
                {"id": 5, "name": "美容时尚","thumb": "","type": 1},
                {"id": 6, "name": "教育培训", "thumb": "", "type": 1},
                {"id": 7, "name": "餐饮食品", "thumb": "", "type": 1},
                {"id": 8, "name": "旅行娱乐", "thumb": "", "type": 1},
                {"id": 9, "name": "家居地产", "thumb": "", "type": 1},
                {"id": 10, "name": "党政", "thumb": "", "type": 1},
                {"id": 29, "name": "影视", "thumb": "", "type": 1},
                {"id": 30, "name": "能源", "thumb": "", "type": 1},
                {"id": 31, "name": "金融银行", "thumb": "", "type": 1},
                {"id": 32, "name": "艺术", "thumb": "", "type": 1},
                {"id": -1, "name": "不限", "thumb": "", "type": 1}
            ],
            "3" : [
                {"id": 21, "name": "商务", "thumb": "http://itbour-back.oss-cn-hangzhou.aliyuncs.com/image/U13396/2017/09/19/180053554_JeFQThrh0EFe9rbUVOIG", "type": 3},
                {"id": 22, "name": "简约", "thumb": "http://itbour-back.oss-cn-hangzhou.aliyuncs.com/image/U13396/2017/09/19/180053182_bMnXjtmCMhIUS5uXlUQD", "type": 3},
                {"id": 23, "name": "复古风", "thumb": "http://itbour-back.oss-cn-hangzhou.aliyuncs.com/image/U13396/2017/09/19/180052164_4ZWxhCpilvDNCfldB1Nw", "type": 3},
                {"id": 24, "name": "创意", "thumb": "http://itbour-back.oss-cn-hangzhou.aliyuncs.com/image/U13396/2017/09/19/18005278_emN6xhb3kCXYA1A8Q4mE", "type": 3},
                {"id": 25, "name": "欧美风", "thumb": "http://itbour-back.oss-cn-hangzhou.aliyuncs.com/image/U13396/2017/09/19/180052310_vQSwqx3urTDmaFLcs7s9", "type": 3},
                {"id": 26, "name": "小清新", "thumb": "http://itbour-back.oss-cn-hangzhou.aliyuncs.com/image/U13396/2017/09/19/18005347_1xsmAso2RN9YDPx1rfvG", "type": 3},
                {"id": 41, "name": "可爱", "thumb": "http://itbour-back.oss-cn-hangzhou.aliyuncs.com/image/U13396/2017/09/19/180052566_Bt6gWBzxQ8YbTU3jEVHC", "type": 3},
                {"id": 42, "name": "中国风", "thumb": "http://itbour-back.oss-cn-hangzhou.aliyuncs.com/image/U13396/2017/09/19/180053326_GmL3zn4wgwAnC3YFxHAV", "type": 3},
                {"id": 43, "name": "酷炫", "thumb": "http://itbour-back.oss-cn-hangzhou.aliyuncs.com/image/U13396/2017/09/19/180051835_G0i5su5cegzlknyi4xR9", "type": 3}
            ],
            "4" : [
                {"id":27,"name":"红","thumb":"http://itbour-back.oss-cn-hangzhou.aliyuncs.com/image/U13396/2017/09/19/175908175_0Rbp6VhRQKuIdKemPzbY","type":4},
                {"id":44,"name":"黄","thumb":"http://itbour-back.oss-cn-hangzhou.aliyuncs.com/image/U13396/2017/09/19/175907716_lHLOexIscdAp8BN0FIZu","type":4},
                {"id":45,"name":"蓝","thumb":"http://itbour-back.oss-cn-hangzhou.aliyuncs.com/image/U13396/2017/09/19/175907632_upGG9pUc4QZH5Io2GyxP","type":4},
                {"id":46,"name":"绿","thumb":"http://itbour-back.oss-cn-hangzhou.aliyuncs.com/image/U13396/2017/09/19/175907391_ze9WoEOiLliJbA0bR77i","type":4},
                {"id":47,"name":"紫","thumb":"http://itbour-back.oss-cn-hangzhou.aliyuncs.com/image/U13396/2017/09/19/175907562_yE27738YNNF6V4wTES3d","type":4},
                {"id":48,"name":"黑","thumb":"http://itbour-back.oss-cn-hangzhou.aliyuncs.com/image/U13396/2017/09/19/175907302_OTxXYritiPdplMAANTXX","type":4},
                {"id":49,"name":"粉","thumb":"http://itbour-back.oss-cn-hangzhou.aliyuncs.com/image/U13396/2017/09/19/175907492_LGDoygT2D30IpUUJYYMH","type":4},
                {"id":50,"name":"白","thumb":"http://itbour-back.oss-cn-hangzhou.aliyuncs.com/image/U13396/2017/09/19/175907253_RSSApTkGHwDmtpvOZ7lF","type":4},
                {"id":51,"name":"灰","thumb":"http://itbour-back.oss-cn-hangzhou.aliyuncs.com/image/U13396/2017/09/19/17590719_aNLI4GNfXW1af8CjNk8U","type":4}
            ]
        };
        return callback(null, obj);
    };

    /**
     * 获取 vi 实验室信息
     *
     * @param callback 回调
     *          err 错误
     *          data 数据
     *
     * */
    labUtil.getInfoQuestions_v6_2 = function(callback) {
        labUtil.getLabQuestionsOptions(function(getOptionsErr, options){
            if(getOptionsErr) {
                return callback(getOptionsErr, null);
            }
            var obj = {
                introduce : {
                    title : "欢迎来到一键生成\n智能实验室",
                    subTitle : "我们将给您最极致的黑科技体验",
                    desc : "智能设计,从LOGO开始\n前方高能, 请做好准备\n即将通往未来世界的大门\n......"
                },
                entries : [
                    {
                        "id":1,
                        "kind":1, // 采集条目的类型, 1. 标示采集用户输入信息
                        "title":"请输入\n您的/公司/店铺/品牌 名称",
                        "desc":"建议输入内容二十字以内",
                        "tips":"请输入您的/公司/店铺/品牌名称",
                        "options":[],
                        "optionW" : 0,
                        "optionH" : 0,
                        "optionC" : 0,
                        "min" : 1, // 最少选择个数
                        "max" : 20 // 最多选择个数
                    },
                    {
                        "id":2,
                        "kind":2, // 采集条目类型, 2, 单选, 下拉列表
                        "title":"您奋斗在哪个行业?",
                        "desc":"没有您所在的行业可选择不限",
                        "tips":"请选择行业",
                        "options":options["1"] || [],
                        "optionW" : 0,
                        "optionH" : 0,
                        "optionC" : 0,
                        "min" : 1, // 最少选择个数
                        "max" : 1 // 最多选择个数
                    },
                    {
                        "id":3,
                        "kind":3, // 采集条目类型, 3, 多选, 方块排列, 尺寸列数取 optionW optionH optionC
                        "title":"您喜欢什么颜色呢?",
                        "desc":"可不选择",
                        "tips":"",
                        "options":options["4"] || [],
                        "optionW" : 225,
                        "optionH" : 225,
                        "optionC" : 3,
                        "min" : 0, // 最少选择个数
                        "max" : 10 // 最多选择个数
                    },
                    {
                        "id": 4,
                        "kind": 3, // 采集条目类型, 3, 多选, 方块排列, 尺寸列数取 optionW optionH optionC
                        "title": "您喜欢什么样的设计风格?",
                        "desc": "可不选择",
                        "tips": "",
                        "options": options["3"] || [],
                        "optionW" : 225,
                        "optionH" : 225,
                        "optionC" : 3,
                        "min" : 0, // 最少选择个数
                        "max" : 10 // 最多选择个数
                    }
                ]
            };

            labUtil.getLabIndustryColor(function(getColorErr,industryColorMap){
                if(getColorErr) {
                    return callback(getColorErr, null);
                }

                for(var i in obj.entries) {
                    var ent = obj.entries[i];

                    for(var j = ent.options.length-1; j>=0; j--) {
                        var opt = ent.options[j];
                        // 注意, nextIds 只管下一级, 行业-->颜色-->风格, 空数组标识不限
                        if(opt.type == 1) { // 行业
                            opt.nextIds = industryColorMap[opt.id] || [];
                            if(opt.nextIds.length == 0 && opt.id != -1) {
                                ent.options.splice(j,1);
                            }
                        }
                        else if(opt.type == 4) { // 颜色
                            opt.nextIds = [];
                        }
                        else if(opt.type == 3) { // 风格
                            opt.nextIds = [];
                        }
                    }
                }

                // 获取不限设置的颜色
                var allColors = [];
                var industry = obj.entries[1];
                for(var i=0; i<industry.options.length; i++) {
                    var opt = industry.options[i];
                    for(var j in opt.nextIds) {
                        var colorId = Number(opt.nextIds[j] || '-1');
                        if(colorId>0 && allColors.indexOf(colorId)<0) {
                            allColors.push(colorId);
                        }
                    }
                }
                for(var i=industry.options.length-1; i>=0;i--) {
                    var opt = industry.options[i];
                    if(opt.id == -1) { // 不限
                        opt.nextIds = allColors;
                    }
                }
                return callback(null, obj);
            });
        });

    };

    /**
     * 根据答案信息参数, 获取对应 id
     *
     * @param userId 用户唯一标识
     * @param typeL 指定作品一级分类
     * @param typeM 指定作品二级分类
     * @param answer 用户选择的答案数组
     * @param append 可能携带的附带文档信息数组
     * @param callback 回调
     *          err: 错误
     *          data: {
     *              typeL : 4,
     *              typeM : 40100,
     *              id : 998
     *          }
     * */
    labUtil.getProductIdByAnswer_v6_2 = function(userId, typeL, typeM, answer, append, callback) {

        // 1: 公司名称(单} 2: 行业(单) 3: 颜色(多) 4: 风格(多)
        var name = null;
        var industry = [];
        var color = null;
        var style = null;
        for(var i = 0;  i< answer.length; i++) {
            var ans = answer[i];
            if(ans.id == 1) { // 公司名称
                name = ans.value[0];
            } else if (ans.id == 2 && Number(ans.value[0]) > 0) { // 行业且选择的不是其他
                industry = ans.value || [];
            } else if (ans.id == 3) { // 颜色
                color = ans.value || [];
            } else if (ans.id == 4) { // 风格
                style = ans.value || [];
            }
        }

        console.log('%%%%%%%%%%%%labUtil.getProductIdByAnswer_v6_2: typeL='+typeL+'&typeM='+typeM+'&industry='+JSON.stringify(industry)+'&color='+JSON.stringify(color)+'&style='+JSON.stringify(style));

        var limit = 3; // 暂时限制必须有两个模板
        if(CONFIG.DEBUG) {
            limit = 2;
        }
        // 1. 获取可使用模板/商品(印品是商品, logo 是模板)
        labUtil.getProductDesigns_v6_2(typeL, typeM, industry, color, style, limit, function(getDesignsErr, list){

            if(getDesignsErr || !list || list.length < limit) {
                return callback(getDesignsErr || '暂无匹配模板', null);
            }
            list = list.slice(0,limit);
            // 2. 取第0个, 创建作品(分 logo 和 名片)
            var design = list[0];
            // logo
            if(typeM == 10100200) {
                //2.1 创建 logo 作品
                labUtil.createLogoProduct_v6_2(userId,{companyName:name},design.id,function(createLogoErr, logoId){
                    if(createLogoErr) {
                        return callback(createLogoErr, null);
                    }
                    // 2.2 缓存 logo 可使用模板至 redis
                    labUtil.cacheProductInfoToRedis_v6_2(logoId,null,list, design.id,function(cacheErr){
                        if (cacheErr) {
                            return callback(cacheErr);
                        }
                        return callback(null, {id:logoId,typeL:typeL, typeM:typeM});
                    });
                });
            }
            // 名片
            else if (typeM = 40100) {
                // 为统一存在和不存在附带信息的情况, 抽出函数使用回调进行处理
                function getCacheAppendInfo(append, getCacheCallback) {
                    if(!append || append.length <=0) {
                        return getCacheCallback(null, null);
                    }
                    labUtil.getRedisCacheProductInfo_v6_2(append[0].id, function(getCacheErr, cache){
                        if(getCacheErr || !cache) {
                            return getCacheCallback(getCacheErr, null);
                        }
                        var logoImgInfo = JSON.parse(cache.logoImg) || {};
                        return getCacheCallback(getCacheErr, logoImgInfo.url)
                    });
                }
                // 2.1 取出附带信息
                getCacheAppendInfo(append, function(getCacheErr, logoImg){
                    if(getCacheErr) {
                        return callback(getCacheErr);
                    }

                    // 2.2 创建名片
                    labUtil.createBussinessCardProduct_v6_2(userId, {companyName:name, logoImg:logoImg},design.id,function(createBCErr, docId){
                        if(createBCErr) {
                            return callback(createBCErr);
                        }
                        // 2.3 缓存名片可用模板列表
                        labUtil.cacheProductInfoToRedis_v6_2(docId,null, list, design.id, function(cacheErr){
                            if(cacheErr) {
                                return callback(cacheErr, null);
                            }

                            return callback(null, {id:docId,typeL:typeL, typeM:typeM});
                        });
                    })
                });
            }
        });
    };



    /**
     * 根据筛选条件, 获取指定分类作品可切换模板列表
     *
     * @param typeL 指定一级分类
     * @param typeM 指定二级分类
     * @param industry 标签数组(行业)如: [1,2,3]
     * @param color 标签数组(颜色)如: [1,2,3]
     * @param style 标签数组(风格)如: [1,2,3]
     * @param limit 返回的最小个数限制
     * @param callback 回调
     *          err: 筛选作品失败原因
     *          list: [
     *              {
     *                  "typeL":4,
     *                  "id":668,
     *                  "vip":0,
     *                  "type_desc":"名片",
     *                  "name":"灰色复古汽车美容名片",
     *                  "w":"1134",
     *                  "h":"709",
     *                  "thumb":"http://itbour-generate.oss-cn-hangzhou.aliyuncs.com/image/U408536/2017/07/20/160126247_wLJlhNkJP6xYnyFRyEvE/0.jpg",
     *                  "author":"宿朝茜",
     *                  "time":"2017-07-19T09:38:26.000Z",
     *                  "useCounts":2740,
     *                  "price":"印刷 20.00/2盒"
     *              }
     *          ]
     *
     * 注意: 筛选出的（Logo）模板/（名片）商品最好是免费的, 筛选出的模板列表中至少要有三个对象, 字段中 id,thumb 必传, 其余随意
     * */
    labUtil.getProductDesigns_v6_2 = function(typeL, typeM, industry, color, style, limit, callback) {
        var types = [];
        if(typeL) types.push(typeL);
        if(typeM) types.push(typeM);


        var keys    = [];
        var values  = [types.join(','), industry.join(','), '',  color.join(','),  style.join(','), '',limit, 0, 10];// 搜索所有
        scriptManager.run('lua3_lab_search', keys, values, function(err, result) {
            if(result && result.length==3){
                return callback(err, JSON.parse(result[1]));
            } else{
                return callback(err, null);
            }
        });
    };

    /**
     * 根据作品 id 缓存作品部分信息至 redis
     *
     * @param docId 作品 id
     * @param logoImg 可为 null, logo 对应的图形缩略图地址, null 标识暂不缓存此字段
     * @param switchList 可为 null, 作品对应的可切换模板/商品列表, null 标识暂不缓存此字段 传入结构为数组, 详见 labUtil.getProductDesigns_v6_2 返回值
     * @param selContentId : 如果是Logo则传入Logo图形的designId（不能传入临时Logo模版的designId），如果是名片则传入名片的designId
     * @param callback 回调
     *          error: 缓存失败原因, 若为 null 标识缓存成功
     * 注意：局部更新，只更新传入的字段
     * */
    labUtil.cacheProductInfoToRedis_v6_2 = function(docId, logoImg, switchList, selContentId, callback) {

        var strLogo = logoImg||'';
        var strSwitch = '';
        if(switchList && switchList.length>0) {
            strSwitch = JSON.stringify(switchList);
        }
        var selContentId = selContentId ||'';
        var keys    = [];
        var values  = [docId, strLogo, strSwitch, selContentId];// 搜索所有
        scriptManager.run('lua3_lab_add_product', keys, values, function(err, result) {
            callback(err, result);
        });
    };

    /**
     * 根据作品 id, 取出缓存至 redis 中的作品相关信息
     *
     * @param docId 作品唯一标识
     * @param callback 回调
     *          error: 取出缓存失败原因
     *          data :  {
     *              logoImg : "http://oss-img.jpg",
     *              switchList : [{}] // 结构见: labUtil.cacheProductInfoToRedis_v6_2 缓存参数 switchList
     *              selContentId : 如果是Logo则传入Logo图形的designId（不能传入临时Logo模版的designId），如果是名片则传入名片的designId
     *          }
     *
     * */
    labUtil.getRedisCacheProductInfo_v6_2 = function(docId, callback) {
        var keys    = [];
        var values  = [docId];// 搜索所有
        scriptManager.run('lua3_lab_get_product', keys, values, function(err, result) {
            if(result && result.length==4){
                var data = {};
                data.logoImg = result[1];
                data.switchList = JSON.parse(result[2]);
                data.selContentId = Number(result[3]);
                return callback(null, data);
            } else{
                return callback(null, null);
            }
        });
    };


    /**
     * [private]建立缓存
     *
     * @param callback 回调
     *          error: 缓存失败原因, 若为 null 标识缓存成功
     *          info:
     * */
    labUtil.initCache = function( callback) {
        // 加载三级分类10100201下面的Logo
        var typeS = 10100201;
        labUtil.initCacheOfTemplate(typeS,null,  function(error){
            console.log(error);
            if(error){
                return callback(error, {});
            }

            // 加载map_id为140的tg_design_doc对应的itb_items
            var mapId = 140;
            labUtil.initCacheOfTemplate(null, mapId, function(error2){
                console.log(error2);
                if(error2){
                    return callback(error2, {});
                }

                // 检查每个行业下的模版，必需大于3个
                labUtil.checkLabTemplate(function(error3, info){
                    console.log(error3);
                    if(error3){
                        return callback(error3, {});
                    }
                    return callback(null, info);
                });


            })
        });
    };

    /**
     * [private]检查每个行业下的模版，必需大于3个，并建立“行业－颜色表”
     * @param callback 回调
     *          error:
     *          info
     * */
    labUtil.checkLabTemplate = function(callback) {
        var limit = CONFIG.DEBUG?2:3;
        var keys    = [];
        var values  = [limit];
        scriptManager.run('lua3_lab_check_industry', keys, values, function(err, result) {
            var ret = {};
            if(result && result[1] && result[1].length>0){
                ret.msg='以下行业下模版少于'+limit;
                ret.ids = result[1];
            }
            callback(err, ret);
        });
    }

    /**
     * [private] 获取“行业－颜色”的映射表
     * @param callback 回调
     *          error:
     *          info:对象类型，结构如下：
     *                  {
     *                      行业ID:[颜色ID],
     *                      行业ID:[颜色ID]
     *                  }
     *               例如：
     *                  {
     *                      1:[27,44,45],
     *                      2:[27,44,45]
     *                  }
     *
     * */
    labUtil.getLabIndustryColor = function(callback) {
        var limit = CONFIG.DEBUG?2:3;
        var keys    = [];
        var values  = [];
        scriptManager.run('lua3_lab_get_industry_color', keys, values, function(err, result) {
            var ret = {};
            if(result && result[1] && result[1].length>0){
                var ics = JSON.parse(result[1]);
                var len = ics.length;
                for(var i=0;i<len;i++){
                    var ic = ics[i];
                    if(ic && ic.length>0){
                        ret[ic[0]] =ic.slice(1);
                    }
                }
            }
            callback(err, ret);
        });
    }


    /**
     * [private]建立Logo缓存
     * @param typeS:  [可选]三级分类id
     * @param mapId: ［可选］分页映射Id
     * @param callback 回调
     *          error: 缓存失败原因, 若为 null 标识缓存成功
     * 注意：局部更新，只更新传入的字段
     * */
    labUtil.initCacheOfTemplate = function(typeS, mapId,  callback) {
        // 处理一页
        function processOnePage(items, callback){
            var asyncFuncs = [];
            for (var i=0;i<items.length;i++) {
                //if(i!=149)    continue;
                asyncFuncs.push((function (index, item) {
                    return function (asyncCallback) {
                        // 添加一个文档
                        labUtil.addDesignToRedis(item.design_id,function(error, ret){
                            return asyncCallback(error, ret);
                        });
                    };
                })(i, items[i])); // 利用闭包解决动态参数传递问题
            }
            async.series(asyncFuncs,function (err, results) {
                var ret=[];
                for(var i=0;i<results.length;i++){
                    ret = ret.concat(results[i]);
                }
                return callback(null, ret);
            });
        }

        // 分页查询
        var newEntity = new TgDesignDocModel({
            publish:1,
            del_flg:0
        });
        if(typeS){
            newEntity.type_id = typeS;
        }
        if(mapId){
            newEntity.map_id=mapId;
        }
        newEntity.findCountFromDB(function(error, count){
            var pageSize = 12;
            var pageCount = Math.ceil((count+pageSize)/pageSize)-1;
            //pageCount=1; // for test

            var asyncFuncs = [];
            for (var i=0;i<pageCount;i++) {
                asyncFuncs.push((function (pageNum) {
                    return function (asyncCallback) {
                        newEntity.findFromDB(function(error, items){
                            processOnePage(items, function(error2, pageFontInfos){
                                return asyncCallback(error, pageFontInfos);
                            });
                        },pageNum*pageSize,pageSize);
                    };
                })(i)); // 利用闭包解决动态参数传递问题
            }
            async.series(asyncFuncs,function (err, results) {
                var ret=[];
                for(var i=0;i<results.length;i++){
                    ret = ret.concat(results[i]);
                }
                return callback(null, ret);
            });
        });

    };

    //------------------------------------------------------------------
    /**
     * 添加模版到缓存中
     * @param designId 设计id／PPT模版id
     * @param callback
     */
    labUtil.addDesignToRedis = function(designId,  callback) {

        // 添加到redis
        function addToRedis(data,callback2){
            if(!data || !data.designId || !data.typeL ||  !data.typeM ||  !data.typeS ||   !data.info  ||  !data.sort){
                console.log('**************** error: get design data failed! '+designId);
                return callback2(null,null);
            }



            var keys    = [];
            var values  = [data.designId, data.typeL, data.typeM, data.typeS,  data.industries, data.scenes, data.colors, data.styles, data.customs, data.info, data.sort];
            scriptManager.run('lua3_lab_add_design', keys, values, function(err, result) {
                return callback2(err, result);
            });
        }
        // 检查名片中是否含有Logo
        // 参数：data,名片的提纲数据(不处理版本号小于3的数据)
        function isBCardHaveLogo(data){
            var LOGO_TOPICS = ["LOGO","Logo","logo"];
            // 解析[logo模版]提纲树
            var logoData = JSON.parse(CommonUtil.process_before_JSON_Parse(data));
            var logoTgTree = new SJGTGV3();
            logoTgTree.fromJson(logoData, logoData.version);

            var findLogo = false;// 是否有Logo
            var count =0;// 循环计数
            var n =logoTgTree.first();
            while(n) {
                if(LOGO_TOPICS.indexOf(n.topic)>=0 && n.h==0 && n.p==0){ // 比较topic且要跳过隐藏节点和保留节点
                    findLogo=true;
                    break;
                }
                n=logoTgTree.next();

                // 防止死循环
                if(count>100) break;
                count++;
            }
            return findLogo;
        }

        labUtil.getInfoOfDesign(designId, function(error, data){
            // 过滤掉版本号小于3的数据
            if(data && data.ver<3){
                console.log('**************** warning: ignore template!, version less then 3 ! '+designId);
                return callback(null,null);
            }
            // 过滤掉不含Logo的名片
            if(data && data.typeL==4 &&  !isBCardHaveLogo(data.data)){
                console.log('**************** warning: ignore template! business card without LOGO ! '+designId);
                return callback(null,null);
            }

            return addToRedis(data,callback);
        });

    };

    //------------------------------------------------------------------
    /**
     * 获取设计的信息
     * @param designId 设计design_id
     * @param callback,参数如下：
     *          error：
     *          data
     *              designId
     *              typeL
     *              typeM
     *              typeS
     *              industries
     *              scenes
     *              colors
     *              styles
     *              customs
     *              priceType  // 费用类型，1免费, 2vip
     *              info
     *              sort 创建时的时间戳作为排序字段
     *              data 提纲数据
     *              ver 版本号
     */
    labUtil.getInfoOfDesign = function(designId, callback) {
        // 获取分类
        var entity = new TgDesignDocModel({
            design_id:designId,
            del_flg:0
        });
        entity.getBaseInfo2(function(error, baseInfo){
            if(error || baseInfo.length==0){
                return callback(error, null);
            }

            entity.getSearchInfo(function(error, searchInfo){
                if(error || searchInfo.length==0){
                    return callback(error, null);
                }


                var s = searchInfo[0];
                if(s.id==null ||   s.w==null || s.h==null || s.thumb==null  || s.price==null){
                    console.log('**************** error: get design data lose  ! '+designId);
                    return callback(error, null);
                }
                s.designId = designId; // 记录designId到搜索结果中

                var data = {
                    designId:designId,
                    typeL:baseInfo[0].typeL ,
                    typeM:baseInfo[0].typeM ,
                    typeS:baseInfo[0].typeS ,
                    industries:baseInfo[0].industries==null?"":baseInfo[0].industries,
                    scenes:baseInfo[0].scenes==null?"":baseInfo[0].scenes,
                    colors:baseInfo[0].colors==null?"":baseInfo[0].colors,
                    styles:baseInfo[0].styles==null?"":baseInfo[0].styles,
                    customs:baseInfo[0].customs==null?"":baseInfo[0].customs,
                    priceType:baseInfo[0].vip==10?2:0 ,
                    info:JSON.stringify(s),
                    sort:baseInfo[0].sort,
                    data:baseInfo[0].data,
                    ver:baseInfo[0].ver,
                };
                return callback(null, data);


            });
        });
    };


    /**
     * 创建 logo 作品, 返回 logo 作品 id
     *
     * @param userId 用户唯一标识
     * @param param 生成 logo 作品的前置参数 {
     *                                          "companyName" : "一键生成"
     *                                     }
     * @param logoId logo模板 id
     * @param callback 回调
     *             error: 生成错误原因
     *             id : 生成的 logo 作品唯一标识
     * */
    labUtil.createLogoProduct_v6_2 = function(userId, param, logoId, callback){
        var previewDId = 3554;// TODO
        if(CONFIG.DEBUG) {
            previewDId=2947;//2944;
        }

        // 预览用模版
        tg3Util.getTgAndFineTuneInfoOfDesign(1010, previewDId, function(err1, previewTmplInfo) {
            if(err1) {
                console.log('labUtil.js [createLogoProduct_v6_2] Find PreviewTmpl Err: '+err1);
                return callback(err1, null);
            }

            if(previewTmplInfo) {

                // logo模版
                tg3Util.getTgAndFineTuneInfoOfDesign(1010, logoId, function(err2, logoTmplInfo) {
                    if(err2) {
                        console.log('labUtil.js [createLogoProduct_v6_2] Find LogoTmpl Err: '+err2);
                        return callback(err2, null);
                    }

                    if(logoTmplInfo) {

                        // 解析[预览用模版]提纲树
                        var tmplData = JSON.parse(previewTmplInfo.coreStructure);
                        var tmplTgTree = new SJGTGV3();
                        tmplTgTree.fromJson(tmplData, tmplData.version);

                        // 微调对象数据
                        var strFtData = (previewTmplInfo.textObjects||'[]')
                            .replace(/\n/g,'\\n').replace(/\t/g,'').replace(/\r/g,'')
                            .replace(/[\x00-\x09\x0B-\x1F\x7F-\x9F]/g, "");
                        var arrFtData = JSON.parse(strFtData);
                        var ftPage = null;
                        if(arrFtData && arrFtData.length>0){
                            ftPage = new SJGPage(new GlobalData());
                            ftPage.fromJsonOfFineTune(arrFtData[0], tmplData.version);
                        } else {
                            return callback('预览模版数据Err', null);
                        }

                        // 解析[logo模版]提纲树
                        var logoData = JSON.parse(logoTmplInfo.coreStructure);
                        var logoTgTree = new SJGTGV3();
                        logoTgTree.fromJson(logoData, logoData.version);

                        // 微调对象数据
                        var strLogoFtData = (logoTmplInfo.textObjects||'[]')
                            .replace(/\n/g,'\\n').replace(/\t/g,'').replace(/\r/g,'')
                            .replace(/[\x00-\x09\x0B-\x1F\x7F-\x9F]/g, "");
                        var arrLogoFtData = JSON.parse(strLogoFtData);
                        var logoFtPage = null;
                        if(arrLogoFtData && arrLogoFtData.length>0){
                            logoFtPage = new SJGPage(new GlobalData());
                            logoFtPage.fromJsonOfFineTune(arrLogoFtData[0], logoData.version);
                        } else {
                            return callback('logo模版数据Err', null);
                        }

                        // 更新[预览用模版]提纲
                        for(var i=0; i<tmplTgTree.root.children.length; i++){
                            var tmplNode = tmplTgTree.root.children[i];

                            // 查找[预览用模版]提纲中的文字节点
                            if(tmplNode && tmplNode.type==1){// 文字节点
                                tmplNode.value.value=param.companyName||'';
                            }

                            // 查找[预览用模版]提纲中的图形节点
                            if(tmplNode && tmplNode.type==5){// 图形节点
                                // 检索[logo模版]中的logo图形节点
                                for(var j=0;j<logoTgTree.root.children.length;j++){
                                    var logoNode = logoTgTree.root.children[j];
                                    if(logoNode && logoNode.type==5) {// 图形节点
                                        // 替换图形
                                        var rw = tmplNode.value.cp.w/logoNode.value.cp.w;
                                        var rh = tmplNode.value.cp.h/logoNode.value.cp.h;
                                        var r = (rw<rh)?rw:rh;
                                        tmplNode.value.cp = logoNode.value.cp.copy();
                                        tmplNode.value.cp.adjustPosition(r,r,2);// 等比缩放
                                        tmplNode.value.gt = logoNode.value.gt;
                                        break;
                                    }
                                }
                            }
                        }

                        // 替换[预览用模版]中的logo颜色和pos
                        var grpChildren = logoFtPage.root.getChildObjOfType(603,false,true);// CLASS_TYPE_GraphObj
                        if(grpChildren && grpChildren.length>0) {
                            var logoGphObj = grpChildren[0];// [logo模版]微调对象

                            var grpChildren2 = ftPage.root.getChildObjOfType(603,false,true);// CLASS_TYPE_GraphObj
                            if(grpChildren2 && grpChildren2.length>0){
                                var tmplGphObj = grpChildren2[0];// [预览模版]微调对象

                                if(logoGphObj.color) {
                                    tmplGphObj.color.fromJson(logoGphObj.color,logoData.version);
                                }
                                if(logoGphObj.pos) {
                                    var rw = tmplGphObj.pos.w/logoGphObj.pos.w;
                                    var rh = tmplGphObj.pos.h/logoGphObj.pos.h;
                                    var r = (rw<rh)?rw:rh;
                                    // 等比缩放
                                    tmplGphObj.pos.w = logoGphObj.pos.w *r;
                                    tmplGphObj.pos.h = logoGphObj.pos.h *r;
                                }
                            }
                        }

                        // 更新后的微调数据
                        var updFt = '['+(ftPage.toJsonOfFineTune()||'')+']';

                        // 创建用户文档
                        var newDocEntity = new TgUserDocModel({
                            tg_id: previewTmplInfo.tg_id,
                            map_id: previewTmplInfo.map_id,
                            design_id: previewTmplInfo.design_id,
                            doc_name: '我的作品',//(logoTmplInfo.designNm||''),
                            user_id: userId,
                            user_type: 1,// 普通
                            purpose: 0,// 普通
                            size_id: previewTmplInfo.size_id,
                            type_id: previewTmplInfo.type_id,
                            data: tmplTgTree.toJson() || '',// 提纲数据
                            hash_tag: previewTmplInfo.hash_tag || '[]',
                            finetune_data: updFt,// 微调数据
                            finetune_flg: 1,
                            ver: tmplData.version || 0,
                            update_by: userId,
                        });
                        newDocEntity.saveToDB(function(crtErr, newDocId){
                            if(crtErr) {
                                console.log('labUtil.js [createLogoProduct_v6_2] Create UserDoc Err: '+crtErr);
                                return callback(crtErr, null);
                            }

                            return callback(null, newDocId);
                        });

                    } else {
                        return callback('未找到logo模版', null);
                    }
                });

            } else {
                return callback('未找到预览模版', null);
            }
        });
    };

    /**
     * 切换用户 logo 作品的模板
     *
     * @param userId 用户唯一标识
     * @param docId 用户作品唯一标识
     * @param logoId logo模板 id
     * @param callback 切换回调
     *          error: 切换错误的原因, 若为 null 标识切换成功
     * */
    labUtil.changeLogoDesign_v6_2 = function(userId, docId, logoId, callback){
        // 用户文档
        var ent1 = new TgUserDocModel({
            doc_id: docId,
            del_flg: 0
        });
        ent1.findFromDB(function(err1, ret1) {
            if(err1) {
                console.log('labUtil.js [changeLogoDesign_v6_2] Find UserDoc Err: '+err1);
                return callback(err1, null);
            }

            if(ret1 && ret1.length>0) {
                var userDocInfo = ret1[0];

                // logo模版
                tg3Util.getTgAndFineTuneInfoOfDesign(1010, logoId, function(err2, logoTmplInfo) {
                    if(err2) {
                        console.log('labUtil.js [changeLogoDesign_v6_2] Find LogoTmpl Err: '+err2);
                        return callback(err2, null);
                    }

                    if(logoTmplInfo) {
                        // 解析[用户文档]提纲树
                        var tmplData = JSON.parse(userDocInfo.data);
                        var tmplTgTree = new SJGTGV3();
                        tmplTgTree.fromJson(tmplData, tmplData.version);

                        // 微调对象数据
                        var strFtData = (userDocInfo.finetune_data||'[]')
                            .replace(/\n/g,'\\n').replace(/\t/g,'').replace(/\r/g,'')
                            .replace(/[\x00-\x09\x0B-\x1F\x7F-\x9F]/g, "");
                        var arrFtData = JSON.parse(strFtData);
                        var ftPage = null;
                        if(arrFtData && arrFtData.length>0){
                            ftPage = new SJGPage(new GlobalData());
                            ftPage.fromJsonOfFineTune(arrFtData[0], tmplData.version);
                        } else {
                            return callback('用户文档数据Err', null);
                        }

                        // 解析[logo模版]提纲树
                        var logoData = JSON.parse(logoTmplInfo.coreStructure);
                        var logoTgTree = new SJGTGV3();
                        logoTgTree.fromJson(logoData, logoData.version);

                        // 微调对象数据
                        var strLogoFtData = (logoTmplInfo.textObjects||'[]')
                            .replace(/\n/g,'\\n').replace(/\t/g,'').replace(/\r/g,'')
                            .replace(/[\x00-\x09\x0B-\x1F\x7F-\x9F]/g, "");
                        var arrLogoFtData = JSON.parse(strLogoFtData);
                        var logoFtPage = null;
                        if(arrLogoFtData && arrLogoFtData.length>0){
                            logoFtPage = new SJGPage(new GlobalData());
                            logoFtPage.fromJsonOfFineTune(arrLogoFtData[0], logoData.version);
                        } else {
                            return callback('logo模版数据Err', null);
                        }

                        // 更新[用户文档]提纲
                        for(var i=0; i<tmplTgTree.root.children.length; i++){
                            var tmplNode = tmplTgTree.root.children[i];

                            // 查找[用户文档]提纲中的图形节点
                            if(tmplNode && tmplNode.type==5){// 图形节点
                                // 检索[logo模版]中的logo图形节点
                                for(var j=0;j<logoTgTree.root.children.length;j++){
                                    var logoNode = logoTgTree.root.children[j];
                                    if(logoNode && logoNode.type==5) {// 图形节点
                                        // 替换图形
                                        var rw = tmplNode.value.cp.w/logoNode.value.cp.w;
                                        var rh = tmplNode.value.cp.h/logoNode.value.cp.h;
                                        var r = (rw<rh)?rw:rh;
                                        tmplNode.value.cp = logoNode.value.cp.copy();
                                        tmplNode.value.cp.adjustPosition(r,r,2);// 等比缩放
                                        tmplNode.value.gt = logoNode.value.gt;
                                        break;
                                    }
                                }
                            }
                        }

                        // 替换[用户文档]中的pos
                        var grpChildren = logoFtPage.root.getChildObjOfType(603,false,true);// CLASS_TYPE_GraphObj
                        if(grpChildren && grpChildren.length>0) {
                            var logoGphObj = grpChildren[0];// [logo模版]微调对象

                            var grpChildren2 = ftPage.root.getChildObjOfType(603,false,true);// CLASS_TYPE_GraphObj
                            if(grpChildren2 && grpChildren2.length>0){
                                var tmplGphObj = grpChildren2[0];// [用户文档]微调对象

                                // 设置pos
                                if(logoGphObj.pos) {
                                    var ox = tmplGphObj.pos.x;
                                    var oy = tmplGphObj.pos.y;
                                    var ow = tmplGphObj.pos.w;
                                    var oh = tmplGphObj.pos.h;
                                    // 以[高宽的最大值为边长的]正方形为边界
                                    var whLimit = (tmplGphObj.pos.w>tmplGphObj.pos.h)?tmplGphObj.pos.w:tmplGphObj.pos.h;

                                    var rw = whLimit/logoGphObj.pos.w;
                                    var rh = whLimit/logoGphObj.pos.h;
                                    var r = (rw<rh)?rw:rh;
                                    // 等比缩放
                                    tmplGphObj.pos.w = logoGphObj.pos.w *r;
                                    tmplGphObj.pos.h = logoGphObj.pos.h *r;
                                    // 位移
                                    tmplGphObj.pos.x = ox+(ow-tmplGphObj.pos.w)/2;
                                    tmplGphObj.pos.y = oy+(oh-tmplGphObj.pos.h)/2;
                                }
                                // 设置color
                                if(logoGphObj.color) {
                                    tmplGphObj.color.fromJson(logoGphObj.color,logoData.version);
                                }
                            }
                        }

                        // 更新后的微调数据
                        var updFt = '['+(ftPage.toJsonOfFineTune()||'')+']';

                        // 更新用户文档
                        var updEnt = new TgUserDocModel({
                            doc_id: docId,
                            data: tmplTgTree.toJson() || '',
                            finetune_data: updFt
                        });
                        updEnt.updateToDB(function(updErr){
                            if(updErr) {
                                console.log('labUtil.js [changeLogoDesign_v6_2] Update UserDoc Err: '+updErr);
                                return callback(updErr, null);
                            }

                            // 清除page／pc
                            labUtil.delDocPgPc(userId, docId, function(delErr){
                                if(delErr) {
                                    console.log('labUtil.js [changeLogoDesign_v6_2] Del UserDocPg Err: '+delErr);
                                }
                                // 缓存logo的selContentId地址到redis
                                labUtil.cacheProductInfoToRedis_v6_2(docId,  null, null, logoId, function(cacheErr, ret){
                                    return callback(cacheErr, null);
                                });
                            });
                        });

                    } else {
                        return callback('未找到logo模版', null);
                    }
                });

            } else {
                return callback('未找到用户文档', null);
            }
        });
    };

    // 删除用户文档page/pc
    labUtil.delDocPgPc = function(userId, docId, cb) {
        // 逻辑删除page
        var delPgEnt = new TgUserPageModel({
            doc_id: docId,
            update_by: userId,
        });
        delPgEnt.delPageLogic(function(delErr){
            if (delErr) {
                console.log('labUtil.js Del UserDocPages Err: ' + delErr);
                return cb(delErr);
            }

            // 逻辑删除pc
            var delPcEnt = new TgUserPcModel({
                doc_id: docId,
                update_by: userId,
            });
            delPcEnt.delPcLogic(function(delErr2){
                if (delErr2) {
                    console.log('labUtil.js Del UserDocPCs Err: ' + delErr2);
                    return cb(delErr2);
                }

                return cb(null);
            });
        });
    };

    /**
     * 创建名片作品, 返回名片作品 id
     *
     * @param userId 用户唯一标识
     * @param param 生成名片作品的前置参数 {
     *                                      "companyName" : "一键生成",
     *                                      "logoImg" : "http://oss-img.jpg"
     *                                  }
     * @param itemId 名片商品的id
     * @param callback 回调
     *             error: 生成错误原因
     *             id : 生成的名片作品唯一标识
     * */
    labUtil.createBussinessCardProduct_v6_2 = function(userId, param, itemId, callback) {
        // 获取模版信息
        (new ItbItemsModel).getItemDesignInfo(itemId, function(getErr, designInfo){
            if(getErr) {
                return callback(getErr, null);
            }

            if(designInfo) {

                getLogoSize(param.logoImg||'', function(err, logoSizeInfo){
                    if(err) {
                        return callback(err, null);
                    }

                    // 解析[模版]提纲树
                    var tmplData = JSON.parse(designInfo.data||'{}');
                    var tmplTgTree = new SJGTGV3();
                    tmplTgTree.fromJson(tmplData, tmplData.version);

                    // 解析微调对象数据
                    var strFtData = (designInfo.finetune_data||'[]')
                        .replace(/\n/g,'\\n').replace(/\t/g,'').replace(/\r/g,'')
                        .replace(/[\x00-\x09\x0B-\x1F\x7F-\x9F]/g, "");
                    var arrFtData = JSON.parse(strFtData);
                    var arrSJGPage = [];
                    if(arrFtData && arrFtData.length>0){
                        for(var i=0; i<arrFtData.length; i++) {
                            var page = new SJGPage(new GlobalData());
                            page.fromJsonOfFineTune(arrFtData[i], tmplData.version);
                            arrSJGPage.push(page);
                        }
                    } else {
                        return callback('模版数据异常', null);
                    }

                    // 更新提纲数据
                    var relations = [];
                    for(var i=0; i<tmplTgTree.root.children.length; i++){
                        var tmplNode = tmplTgTree.root.children[i];

                        // 文字节点
                        if(tmplNode && tmplNode.type==1) {
                            if(tmplNode.topic && tmplNode.topic.indexOf("公司名称") != -1) {
                                tmplNode.value.value = param.companyName||'';
                            }
                        }
                        // 图像节点
                        if(tmplNode && tmplNode.type==2){
                            if(tmplNode.topic && (tmplNode.topic||'').toLowerCase().indexOf("logo") != -1) {
                                tmplNode.value.value = param.logoImg||'';
                                if(tmplNode.value.pos) {
                                    tmplNode.value.pos.x = 0;
                                    tmplNode.value.pos.y = 0;
                                    tmplNode.value.pos.w = logoSizeInfo.w;
                                    tmplNode.value.pos.h = logoSizeInfo.h;
                                }
                                if(tmplNode.value.mask) {
                                    tmplNode.value.mask = ApiComUtil.createCompoundPath(0/*矩形*/,logoSizeInfo.w,logoSizeInfo.h);
                                }
                                relations = relations.concat(tmplNode.relations);
                            }
                        }
                    }

                    // 更新微调数据
                    if(logoSizeInfo && Number(logoSizeInfo.w||'0')>0 && Number(logoSizeInfo.h||'0')>0) {
                        // 循环页
                        for (var i = 0; i < arrSJGPage.length; i++) {
                            var page = arrSJGPage[i];

                            var imgChildren = page.root.getChildObjOfType(602, false, true);// CLASS_TYPE_ImageObj
                            if (imgChildren && imgChildren.length > 0) {
                                // 循环图像对象
                                for (var m = 0; m < imgChildren.length; m++) {
                                    var imgObj = imgChildren[m];

                                    // 循环对应关系
                                    for (var n = 0; n < relations.length; n++) {
                                        var rel = relations[n];

                                        // 找到logo对象
                                        if (rel.page_index == i && rel.obj_id == imgObj.id) {
                                            var maxW = imgObj.pos.w;
                                            var maxH = imgObj.pos.h;
                                            var orgX = imgObj.pos.x;
                                            var orgY = imgObj.pos.y;

                                            // 目前图片只支持等比缩放
                                            // 改为logo高宽
                                            imgObj.pos.w = logoSizeInfo.w;
                                            imgObj.pos.h = logoSizeInfo.h;

                                            var ratioW = maxW / imgObj.pos.w || 1; // x缩放比例
                                            var ratioH = maxH / imgObj.pos.h || 1; // y缩放比例
                                            var ratio = (ratioW < ratioH) ? ratioW : ratioH;
                                            // 缩放logo到原pos框内
                                            imgObj.pos.w *= ratio;
                                            imgObj.pos.h *= ratio;
                                            // 居中到原pos框内
                                            imgObj.pos.x += (maxW-imgObj.pos.w)/2;
                                            imgObj.pos.y += (maxH-imgObj.pos.h)/2;

                                            if(imgObj.image) {// 图片大小
                                                imgObj.image.x=0;
                                                imgObj.image.y=0;
                                                imgObj.image.w=imgObj.pos.w;
                                                imgObj.image.h=imgObj.pos.h;
                                            }
                                            // 重建mask
                                            imgObj.mask = ApiComUtil.createCompoundPath(0/*矩形*/,imgObj.pos.w,imgObj.pos.h);
                                        }
                                    }
                                }
                            }
                        }
                    }

                    // 更新后的微调数据
                    var updFt = '';
                    for (var i = 0; i < arrSJGPage.length; i++){
                        var page = arrSJGPage[i];
                        if(i>0) {
                            updFt += ',';
                        }
                        updFt += page.toJsonOfFineTune()||'';
                    }
                    updFt = '['+updFt+']';

                    // 创建用户文档
                    var newDocEntity = new TgUserDocModel({
                        tg_id: designInfo.tg_id,
                        map_id: designInfo.map_id,
                        design_id: designInfo.design_id,
                        doc_name: '我的作品',// (designInfo.design_name||'')
                        user_id: userId,
                        user_type: 1,// 普通
                        purpose: 0,// TODO 0.普通, 2.印品订单作品
                        size_id: designInfo.size_id,
                        type_id: designInfo.type_id,
                        data: tmplTgTree.toJson() || '',// 提纲数据
                        hash_tag: designInfo.hash_tag || '[]',
                        finetune_data: updFt,// 微调数据
                        finetune_flg: 1,
                        ver: designInfo.ver,
                        update_by: userId,
                    });
                    newDocEntity.saveToDB(function(crtErr, newDocId){
                        if(crtErr) {
                            console.log('labUtil.js [createBussinessCardProduct_v6_2] Create UserDoc Err: '+crtErr);
                            return callback(crtErr, null);
                        }
                        return callback(null, newDocId);
                    });

                });

            } else {
                return callback('未找到对应模版', null);
            }
        });

        // TODO
        function getLogoSize(imgUrl, cb){
            tg3Util.getOssImgSize(imgUrl, function(err, ret){
                return cb(err, ret||{w:0,h:0});
            });
        }
    };

    /**
     * 切换用户名片作品的模板
     *
     * @param useId 用户唯一标识
     * @param docId 用户作品唯一标识
     * @param itemId 名片商品的id
     * @param callback 切换回调
     *          error: 切换错误的原因, 若为 null 标识切换成功
     * */
    labUtil.changeBussinessCardDesign_v6_2 = function(useId, docId, itemId, callback) {
        // 用户文档
        var ent1 = new TgUserDocModel({
            doc_id: docId,
            del_flg: 0
        });
        ent1.findFromDB(function(err1, ret1) {
            if (err1) {
                console.log('labUtil.js [changeBussinessCardDesign_v6_2] Find UserDoc Err: ' + err1);
                return callback(err1, null);
            }

            if (ret1 && ret1.length > 0) {
                var userDocInfo = ret1[0];

                // 获取模版信息
                (new ItbItemsModel).getItemDesignInfo(itemId, function(getErr, designInfo){
                    if(getErr) {
                        console.log('labUtil.js [changeBussinessCardDesign_v6_2] Find ItemDesign Err: ' + getErr);
                        return callback(getErr, null);
                    }

                    if(designInfo) {

                        // 检查提纲是否相同
                        if(userDocInfo.tg_id!=designInfo.tg_id || userDocInfo.map_id!=designInfo.map_id) {
                            return callback('模版不匹配', null);
                        }

                        //#####################################################
                        // 解析[用户文档]提纲树
                        var docData = JSON.parse(userDocInfo.data);
                        var docTgTree = new SJGTGV3();
                        docTgTree.fromJson(docData, docData.version);

                        // 微调对象数据
                        var strDocFtData = (userDocInfo.finetune_data||'[]')
                            .replace(/\n/g,'\\n').replace(/\t/g,'').replace(/\r/g,'')
                            .replace(/[\x00-\x09\x0B-\x1F\x7F-\x9F]/g, "");
                        var arrDocFtData = JSON.parse(strDocFtData);
                        var arrDocSJGPage = [];
                        if(arrDocFtData && arrDocFtData.length>0){
                            for(var i=0; i<arrDocFtData.length; i++) {
                                var page = new SJGPage(new GlobalData());
                                page.fromJsonOfFineTune(arrDocFtData[i], docData.version);
                                arrDocSJGPage.push(page);
                            }
                        } else {
                            return callback('用户文档数据异常', null);
                        }

                        //#####################################################
                        // 解析[模版]提纲树
                        var tmplData = JSON.parse(designInfo.data||'{}');
                        var tmplTgTree = new SJGTGV3();
                        tmplTgTree.fromJson(tmplData, tmplData.version);

                        // 解析微调对象数据
                        var strTmplFtData = (designInfo.finetune_data||'[]')
                            .replace(/\n/g,'\\n').replace(/\t/g,'').replace(/\r/g,'')
                            .replace(/[\x00-\x09\x0B-\x1F\x7F-\x9F]/g, "");
                        var arrTmplFtData = JSON.parse(strTmplFtData);
                        var arrTmplSJGPage = [];
                        if(arrTmplFtData && arrTmplFtData.length>0){
                            for(var i=0; i<arrTmplFtData.length; i++) {
                                var page = new SJGPage(new GlobalData());
                                page.fromJsonOfFineTune(arrTmplFtData[i], tmplData.version);
                                arrTmplSJGPage.push(page);
                            }
                        } else {
                            return callback('模版数据异常', null);
                        }

                        //#####################################################
                        // 更新目标模版提纲数据
                        var relations = [];
                        for(var i=0; i<tmplTgTree.root.children.length; i++){
                            var tmplNode = tmplTgTree.root.children[i];

                            // 循环用户文档找对应节点
                            for(var m=0; m<docTgTree.root.children.length; m++) {
                                var docNode = docTgTree.root.children[m];

                                if(tmplNode && docNode
                                    && tmplNode.type==docNode.type// 节点类型相同
                                    && tmplNode.o==docNode.o) {// 0表示普通节点／1表示可选／2表示新增节点

                                    var tNodeNm = (tmplNode.topic||'').toLowerCase();
                                    var dNodeNm = (docNode.topic||'').toLowerCase();
                                    if(tNodeNm && tNodeNm.length>0 && dNodeNm && dNodeNm.length>0
                                        && tNodeNm==dNodeNm) {// 节点名称相同

                                        if(docNode.h==0) {// 未隐藏
                                            // 拷贝内容
                                            tmplNode.value = docNode.value;
                                        }
                                    }
                                }
                            }
                        }

                        //#####################################################
                        // TODO 暂不处理微调数据

                        // 更新用户文档
                        var updEnt = new TgUserDocModel({
                            doc_id: docId,
                            tg_id: designInfo.tg_id,
                            map_id: designInfo.map_id,
                            design_id: designInfo.design_id,// 更新设计模版
                            data: tmplTgTree.toJson() || '',// 更新提纲树
                            finetune_data: '',// 清除微调
                            finetune_flg: 0
                        });
                        updEnt.updateToDB(function(updErr){
                            if(updErr) {
                                console.log('labUtil.js [changeBussinessCardDesign_v6_2] Update UserDoc Err: '+updErr);
                                return callback(updErr, null);
                            }

                            // 清除page／pc
                            labUtil.delDocPgPc(userDocInfo.user_id, docId, function(delErr){
                                if(delErr) {
                                    console.log('labUtil.js [changeBussinessCardDesign_v6_2] Del UserDocPg Err: '+delErr);
                                }

                                // 缓存名片的selContentId地址到redis
                                labUtil.cacheProductInfoToRedis_v6_2(docId,  null, null, designInfo.design_id, function(cacheErr, ret){
                                    return callback(cacheErr, null);
                                });
                            });
                        });

                    } else {
                        return callback('未找到对应模版', null);
                    }
                });
            } else {
                return callback('未找到用户文档', null);
            }
        });
    };

    /**
     * 预览Logo用户作品, 若作品未排版则排版(不支持 ppt)
     *
     * @param docId 用户作品唯一标识
     * @param callback 预览结果
     *          error: 预览错误原因
     *          data: {
     *          		"id" : 389,
     *          		"typeL" : 4,
     *          		"designId" : 1,
     *          		"docNm": "黄色简约企业logo",
     *          		"w" : 1240,
     *          		"h" : 1683,
     *          		"previews" : ["http://oss-itbour-image.jpg"]
     *          	}
     * 注意：生成Logo作品预览图之外， 还需要将Logo部分单独生成图片缓存到redis，key是作品id（调用labUtil.cacheProductInfoToRedis_v6_2）
     * */
    labUtil.previewLogo_v6_2 = function(docId,callback) {

        // 获取文档信息
        var ent = new TgUserDocModel({
            doc_id: docId,
            withoutPgInfo: 1
        });
        ent.getDocInfoById(function(error, ret){
            if(error) {
                return callback(error, null);
            }

            if(ret && ret.length>0) {
                var docInfo = ret[0];

                var retData = {
                    id: docInfo.doc_id,
                    typeL: docInfo.typeL,
                    designId: docInfo.design_id,
                    docNm: docInfo.doc_name||'',
                    w: docInfo.width||0,
                    h: docInfo.height||0,
                    previews:[],
                    logoUrl: '',
                    logoW: 0,
                    logoH: 0
                };

                // 获取文档页信息
                var pgEntity = new TgUserPageModel({
                    doc_id: docId,
                    del_flg:0
                });
                pgEntity.getPageInfoById(function(err, retPages){
                    if(err){
                        return callback(err, null);
                    }

                    var doTypeset = false;
                    //if (retPages && retPages.length > 0) {
                    //    for(var i in retPages){
                    //        var item = retPages[i];
                    //
                    //        // 只要有未生成预览图就排版
                    //        if (item.thumb == null || item.thumb.trim().length == 0) {
                    //            doTypeset = true;
                    //            break;
                    //        }
                    //
                    //        retData.previews.push(item.thumb);
                    //    }
                    //} else {
                    //    doTypeset = true;
                    //}
                    doTypeset = true; // 强制每次预览logo都排版, 缓存 logo 的图形图片
                    if(doTypeset) {
                        // 清除page／pc, 确保预览图不会重复出现
                        labUtil.delDocPgPc(docInfo.user_id, docId, function(delErr){
                            if(delErr) {
                                console.log('labUtil.js [changeBussinessCardDesign_v6_2] Del UserDocPg Err: '+delErr);
                            }

                            // 需要排版
                            rpcFunc.typesetTGDoc(docId, function (rpcRet) {

                                // 生成logo
                                labUtil.getLogoImgInfo(docInfo,true,function(procErr, retLogoInfo){
                                    if(procErr){
                                        console.log(procErr);
                                        return callback(procErr, null);
                                    }

                                    retData.logoUrl = retLogoInfo.url||'';
                                    retData.logoW = retLogoInfo.w||0;
                                    retData.logoH = retLogoInfo.h||0;

                                    // 再次获取页信息
                                    pgEntity.getPageInfoById(function(err2, retPages2){
                                        if(err2) {
                                            return callback(err2, null);
                                        }

                                        if (retPages2 && retPages2.length > 0) {
                                            for(var j in retPages2){
                                                var item = retPages2[j];

                                                // TODO 只要有未生成预览图就报错
                                                if (item.thumb == null || item.thumb.trim().length == 0) {
                                                    return callback('生成预览图失败', null);
                                                }

                                                retData.previews.push(item.thumb);
                                            }
                                        }

                                        return callback(null, retData);
                                    });
                                });
                            });
                        });
                    } else {
                        // 无需排版
                        labUtil.getLogoImgInfo(docInfo,false,function(procErr, retLogoInfo){
                            retData.logoUrl = retLogoInfo.url||'';
                            retData.logoW = retLogoInfo.w||0;
                            retData.logoH = retLogoInfo.h||0;
                            return callback(null, retData);
                        });
                    }

                })

            } else {
                return callback('文档不存在', null);
            }
        });
    };

    /**
     * 获取logo图片信息
     * docModel: 用户文档(根据logo预览用模版生成)
     * bForce: 不读redis，直接生成logo
     */
    labUtil.getLogoImgInfo = function(docModel, bForce, callback) {
        // 生成logo图片的最大高宽
        var LOGO_LIMIT_SIZE = 400;// TODO
        var logoW = 0;
        var logoH = 0;

        if(bForce) {
            logoGraphProc(docModel, function(procErr, procRet) {
                return callback(procErr, procRet);
            });
        } else {
            // 读redis缓存
            labUtil.getRedisCacheProductInfo_v6_2(docModel.doc_id, function(getErr, getRet) {
                if(getRet && getRet.logoImg && getRet.logoImg.length>0) {
                    // 能获取则直接返回
                    return callback(null, JSON.parse(getRet.logoImg));
                }

                logoGraphProc(docModel, function(procErr, procRet) {
                    return callback(procErr, procRet);
                });
            });
        }

        // 根据graph生成image
        function logoGraphProc(docModel, cb) {
            // 解析[用户文档]提纲树
            var tmplData = JSON.parse(docModel.data);
            var tmplTgTree = new SJGTGV3();
            tmplTgTree.fromJson(tmplData, tmplData.version);

            // 微调对象数据
            var strFtData = (docModel.finetune_data||'[]')
                .replace(/\n/g,'\\n').replace(/\t/g,'').replace(/\r/g,'')
                .replace(/[\x00-\x09\x0B-\x1F\x7F-\x9F]/g, "");
            var arrFtData = JSON.parse(strFtData);
            var ftPage = null;
            if(arrFtData && arrFtData.length>0){
                ftPage = new SJGPage(new GlobalData());
                ftPage.fromJsonOfFineTune(arrFtData[0], tmplData.version);
            } else {
                return cb('用户文档数据Err', null);
            }

            // 查找[用户文档]提纲中的图形节点
            var cp = null;
            for(var i=0; i<tmplTgTree.root.children.length; i++){
                var tmplNode = tmplTgTree.root.children[i];
                if(tmplNode && tmplNode.type==5){// 图形节点
                    cp = tmplNode.value.cp.copy();
                    break;
                }
            }

            // 查找[用户文档]微调信息中的pos和color
            var color = new FColor();
            var grpChildren = ftPage.root.getChildObjOfType(603,false,true);// CLASS_TYPE_GraphObj
            if(grpChildren && grpChildren.length>0){
                var tmplGphObj = grpChildren[0];// [用户文档]微调对象
                if(cp) {
                    // 先根据pos缩放,保证高宽比
                    cp.adjustPosition(tmplGphObj.pos.w/cp.w,
                        tmplGphObj.pos.h/cp.h,2);

                    // 再等比缩放到指定大小
                    var rw = LOGO_LIMIT_SIZE/cp.w;
                    var rh = LOGO_LIMIT_SIZE/cp.h;
                    var r = (rw<rh)?rw:rh;
                    cp.adjustPosition(r,r,2);// 等比缩放

                    logoW = cp.w;
                    logoH = cp.h;

                    if(tmplGphObj.color) {
                        color = tmplGphObj.color;
                    }
                }
            }

            if(cp) {
                rpcFunc.createColorImageOfCompoundPath(cp.toJson(), tmplData.version, docModel.user_id,
                    color.r, color.g, color.b, function(retUrl){

                        var retInfo = {url:retUrl||'', w:logoW, h:logoH};

                        if(retUrl && retUrl.length>0) {
                            var imgInfo = JSON.stringify(retInfo);
                            // 缓存logo图片地址到redis
                            labUtil.cacheProductInfoToRedis_v6_2(docModel.doc_id, imgInfo, null, null, function(err, ret){
                                return cb(null, retInfo);
                            });

                        } else {
                            return cb('生成图片失败', retInfo);
                        }
                    }
                );
            } else {
                return cb('未获取到图形',null);
            }
        }
    };

    /**
     * 预览名片用户作品, 若作品未排版则排版(不支持 ppt)
     *
     * @param docId 用户作品唯一标识
     * @param callback 预览结果
     *          error: 预览错误原因
     *          data: {
     *          		"id" : 389,
     *          		"typeL" : 4,
     *          		"designId" : 1,
     *          		"docNm": "黄色简约企业logo",
     *          		"w" : 1240,
     *          		"h" : 1683,
     *          		"previews" : ["http://oss-itbour-image.jpg"]
     *          	}
     * */
    labUtil.previewBussinessCard_v6_2 = function(docId,callback) {
        // 获取文档信息
        var ent = new TgUserDocModel({
            doc_id: docId,
            withoutPgInfo: 1
        });
        ent.getDocInfoById(function(error, ret){
            if(error) {
                return callback(error, null);
            }

            if(ret && ret.length>0) {
                var docInfo = ret[0];

                var retData = {
                    id: docInfo.doc_id,
                    typeL: docInfo.typeL,
                    designId: docInfo.design_id,
                    docNm: docInfo.doc_name||'',
                    w: docInfo.width||0,
                    h: docInfo.height||0,
                    previews:[]
                };

                // 获取文档页信息
                var pgEntity = new TgUserPageModel({
                    doc_id: docId,
                    del_flg:0
                });
                pgEntity.getPageInfoById(function(err, retPages){
                    if(err){
                        return callback(err, null);
                    }

                    var doTypeset = false;
                    if (retPages && retPages.length > 0) {
                        for(var i in retPages){
                            var item = retPages[i];

                            // 只要有未生成预览图就排版
                            if (item.thumb == null || item.thumb.trim().length == 0) {
                                doTypeset = true;
                                break;
                            }

                            retData.previews.push(item.thumb);
                        }
                    } else {
                        doTypeset = true;
                    }

                    if(doTypeset) {
                        // 需要排版
                        rpcFunc.typesetTGDoc(docId, function (rpcRet) {
                            // 再次获取页信息
                            pgEntity.getPageInfoById(function(err2, retPages2){
                                if(err2) {
                                    return callback(err2, null);
                                }

                                if (retPages2 && retPages2.length > 0) {
                                    for(var j in retPages2){
                                        var item = retPages2[j];

                                        // TODO 只要有未生成预览图就报错
                                        if (item.thumb == null || item.thumb.trim().length == 0) {
                                            return callback('生成预览图失败', null);
                                        }

                                        retData.previews.push(item.thumb);
                                    }
                                }

                                return callback(null, retData);
                            });
                        });
                    } else {
                        // 无需排版
                        return callback(null, retData);
                    }
                })
            } else {
                return callback('文档不存在', null);
            }
        });
    };

    /**
     * 根据作品 id 和指定模板 id 获取作品预览图
     *
     * @param userId 用户唯一标识
     * @param typeL 作品一级分类 暂时只支持 4, 1010 (印品和 loho)
     * @param docId 作品唯一标识
     * @param designId 指定模板
     * @param callback 回调
     *          err: 错误原因
     *           data: {
 	 * 	             "id" : 389,
 	 * 	             "typeL" : 4,
 	 * 	             "designId" : 1,
 	 * 	             "docNm": "黄色简约企业logo",
 	 * 	             "w" : 1240,
 	 * 	             "h" : 1683,
 	 * 	             "previews" : ["http://oss-itbour-image.jpg"],
 	 * 	             "designs" : [{id:1,thumb:'http://oss-img.jpg'}]
 	 *             }
     *
     * */
    labUtil.getProductPreviewById_v6_2 = function(userId, typeL, docId, designId, callback) {

        // 1. 不切换, 仅预览
        if(designId <=0) { // 不指定, 仅预览
            // 1.1 获取缓存信息
            labUtil.getRedisCacheProductInfo_v6_2(docId, function(getCacheErr, cacheInfo){
                if(getCacheErr) {
                    return callback(getCacheErr, null);
                }
                // 1.2 如果是印品, 获取印品预览信息
                if(typeL == CONFIG.DOC_TYPE_4) {
                    labUtil.previewBussinessCard_v6_2(docId, function(previewBCErr, info) {
                        if(previewBCErr) {
                            return callback(previewBCErr);
                        }
                        info.designs = cacheInfo.switchList;
                        info.selContentId = cacheInfo.selContentId;
                        return callback(null,info);
                    });
                }
                // 1.3 如果是logo, 获取logo预览信息
                else if (typeL == CONFIG.DOC_TYPE_1010) {
                    labUtil.previewLogo_v6_2(docId, function(previewLogoErr, info){
                        if(previewLogoErr) {
                            return callback(previewLogoErr, null);
                        }
                        info.designs = cacheInfo.switchList;
                        info.selContentId = cacheInfo.selContentId;
                        return callback(previewLogoErr, info);
                    });
                }
                return;

            });
            return;
        }

        // 2. 切换模板
        if (typeL == CONFIG.DOC_TYPE_4) {
            // 2.1 切换模板
            labUtil.changeBussinessCardDesign_v6_2(userId, docId, designId, function(changeErr){
                if(changeErr) {
                    return callback(changeErr, null);
                }
                // 2.2 预览作品
                labUtil.previewBussinessCard_v6_2(docId, function(previewBCErr, info) {
                    if(previewBCErr) {
                        return callback(previewBCErr);
                    }

                    // 2.3 获取缓存信息
                    labUtil.getRedisCacheProductInfo_v6_2(docId, function(getCacheErr, cacheInfo){
                        if(getCacheErr) {
                            return callback(getCacheErr, null);
                        }
                        info.designs = cacheInfo.switchList;
                        info.selContentId = cacheInfo.selContentId;
                        return callback(getCacheErr,info);
                    });
                });

            })
        }
        else if(typeL == CONFIG.DOC_TYPE_1010) {
            // 2.1  切换模板
            labUtil.changeLogoDesign_v6_2(userId, docId,designId, function(changeErr){
                if(changeErr) {
                    return callback(changeErr, null);
                }
                // 2.2 预览作品
                labUtil.previewLogo_v6_2(docId, function(previewLogoErr, info){
                    if(previewLogoErr) {
                        return callback(previewLogoErr, null);
                    }

                    // 2.3 获取缓存信息
                    labUtil.getRedisCacheProductInfo_v6_2(docId, function(getCacheErr, cacheInfo){
                        if(getCacheErr) {
                            return callback(getCacheErr, null);
                        }

                        info.designs = cacheInfo.switchList;
                        info.selContentId = cacheInfo.selContentId;
                        return callback(getCacheErr, info);
                    });
                });
            });
        }
    };


    /**
     * 存储错误日志至数据库
     *
     * @param device 设备标识
     * @param userId 用户标识
     * @param deviceInfo 设备信息
     * @param errorLog 错误日志
     * @param callback 错误回调
     *
     * */
    labUtil.uploadUserDeviceErrorLog_v6_2 = function(device, userId, deviceInfo, errorLog, callback){

        var entity = new ItbFeedBackModel({
            type : 20, /**app 错误日志标记*/
            device_info_sys : deviceInfo || '',
            user_id : userId || 0,
            advice : errorLog || '',
            update_by : userId || ''
        });
        entity.saveToDB(function(saveErr, inserId){

            return callback(saveErr, inserId);
        });
    };


    /*
    * 获取视频模板/作品, 提纲及视频信息
    *
    * @param userId 用户唯一标识
    * @param docId 视频模板/作品唯一标识
    * @param isDesign 0/1, 0 不是模板, 1 是模板
    * @param callback 回调
    *           error: 错误
    *           data :  提纲+预览信息
    * */
    labUtil.getVideoTgInfo_v6_3 = function(userId, docId, isDesign, callback) {
        var entity = isDesign ? (new VideoDesignDocModel()) : (new VideoUserDocModel());
        // 模板
        if(isDesign) {
            entity.getDesignDocInfo(docId, function(getDesignErr, designRow){
                if(getDesignErr || !designRow) {
                    return callback(getDesignErr || '无此模板', null);
                }
                // 模板发布前已预览, 故不需要排版
                var ret = {
                    designId : designRow.design_id,
                    designNm : designRow.design_name,
                    productId : 0, // 模板数据, 没有作品信息
                    productNm : '',
                    coreStructure : JSON.parse(designRow.tg_data),
                    videoInfo : {
                        videoWidth : designRow.width || 0,
                        videoHeight : designRow.height || 0,
                        videoDuration : designRow.duration || 0, // 单位: 秒
                        videoUrl : designRow.video,
                        videoThumb: designRow.thumb,
                    }
                };
                return callback(null, ret);
            });
            return;
        }
        // 作品
        entity.getProductInfo(docId, userId, function(getProductErr, productRow){

            if(getProductErr || !productRow) {
                return callback(getProductErr || '无此作品', null);
            }
            var ret = {
                designId : productRow.design_id,
                designNm : productRow.design_name,
                productId : productRow.doc_id, // 模板数据, 没有作品信息
                productNm : productRow.doc_name,
                coreStructure : JSON.parse(productRow.tg_data)
            };
            //// 不需要重新排版
            //if((productRow.video && productRow.video.length) &&        // 视频地址存在
            //    (productRow.thumb && productRow.thumb.length) &&        // 视频缩略图存在
            //    productRow.duration > 0)                                // 视频时长大于 0s
            //{
            //   ret.videoInfo = {
            //       videoWidth : productRow.width || 0,
            //       videoHeight : productRow.height || 0,
            //       videoDuration : productRow.duration || 0, // 单位: 秒
            //       videoUrl : productRow.video,
            //       videoThumb: productRow.thumb,
            //   };
            //    return callback(null, ret);
            //}

            // 获取视频信息(未排版自动排版, 已排版就直接返回)
            labUtil.getVideoPreviewInfo_v6_3(userId, docId, isDesign, 0/**不需要强制排版*/, function(getVideoInfoErr, videoInfo){
                if(getVideoInfoErr) {
                    return callback(getVideoInfoErr, null);
                }
                ret.videoInfo = videoInfo;
                return callback(null, ret);
            });
        });
    };

    /**
     * 获取视频作品/模板预览信息
     *
     * @param userId 用户唯一标识
     * @param docId 视频作品/模板唯一标识
     * @param isDesign 0/1 是否是模板, 0 不是模板, 1 是模板
     * @param bForce 0/1 是否强制重新排版, 0, 不强制, 1 强制
     * @param callback
     *             err 错误
     *             videoInfo : {
                                  "videoWidth": 720,                    // 视频宽
                                  "videoHeight": 1280,                  // 视频高
                                  "videoDuration": 10,                  // 视频时长
                                  "videoUrl" : "http://itbour-generate.img-cn-hangzhou.aliyuncs.com/video/1.mp4",  // 视频 url
                                  "videoThumb" : "http://itbour-generate.img-cn-hangzhou.aliyuncs.com/video/thumb/1.jpg", // 视频缩略图
                                }
     *
     * */
    labUtil.getVideoPreviewInfo_v6_3 = function(userId, docId, isDesign, bForce, callback) {
        var entity = isDesign ? (new VideoDesignDocModel()) : (new VideoUserDocModel());
        // 模板
        if(isDesign) {
            entity.getDesignDocInfo(docId, function(getDesignErr, designRow){
                if(getDesignErr || !designRow) {
                    return callback(getDesignErr || '无此模板', null);
                }
                // 不需要重新排版
                //if( !bForce &&                                              // 不强制重新排版
                //    (designRow.video && designRow.video.length) &&        // 视频地址存在
                //    (designRow.thumb && designRow.thumb.length) &&        // 视频缩略图存在
                //    designRow.duration > 0)                                // 视频时长大于 0s
                //{
                if( !bForce && designRow.video && designRow.video.length)
                {
                    var videoInfo = {
                        videoWidth : designRow.width || 0,
                        videoHeight : designRow.height || 0,
                        videoDuration : designRow.duration || 0, // 单位: 秒
                        videoUrl : designRow.video,
                        videoThumb: designRow.thumb,
                    };
                    return callback(null, videoInfo);
                }
                // 重新排版(未排版或者强制排版)
                labUtil.generateDesignVideo(docId, function(generateErr, videoInfo){
                    return callback(generateErr, videoInfo);
                });
            });
            return;
        }
        // 作品
        entity.getProductInfo(docId, userId, function(getProductErr, productRow){
            if(getProductErr || !productRow) {
                return callback(getProductErr || '无此作品', null);
            }
            // 不需要重新排版
            //if( !bForce &&                                              // 不强制重新排版
            //    (productRow.video && productRow.video.length) &&        // 视频地址存在
            //    (productRow.thumb && productRow.thumb.length) &&        // 视频缩略图存在
            //    productRow.duration > 0)                                // 视频时长大于 0s
            //{
            if(!bForce && productRow.video && productRow.video.length)
            {
                var videoInfo = {
                    videoWidth : productRow.width || 0,
                    videoHeight : productRow.height || 0,
                    videoDuration : productRow.duration || 0, // 单位: 秒
                    videoUrl : productRow.video,
                    videoThumb: productRow.thumb,
                };
                return callback(null, videoInfo);
            }
            // 重新排版(未排版或者强制排版)
            labUtil.generateProductVideo(docId, function(generateErr, videoInfo){
                return callback(generateErr, videoInfo);
            })
        });
    };

    /**
     * 排版模板视频
     *
     * @param designId 模板唯一标识
     * @param callback 回调
     *          err: 排版视频失败
 *             videoInfo : {
                              "videoWidth": 720,                    // 视频宽
                              "videoHeight": 1280,                  // 视频高
                              "videoDuration": 10,                  // 视频时长
                              "videoUrl" : "http://itbour-generate.img-cn-hangzhou.aliyuncs.com/video/1.mp4",  // 视频 url
                              "videoThumb" : "http://itbour-generate.img-cn-hangzhou.aliyuncs.com/video/thumb/1.jpg", // 视频缩略图
                            }
     * */
    labUtil.generateDesignVideo = function(designId, callback){
        rpcFunc.createDesignVideo(designId,function(error, result){
            if(error) {
                return callback(error, null);
            }
            return callback(error, result);
        });
    };

    /**
     * 排版作品视频
     *
     * @param productId 模板唯一标识
     * @param callback 回调
     *          err: 排版视频失败
     *             videoInfo : {
                              "videoWidth": 720,                    // 视频宽
                              "videoHeight": 1280,                  // 视频高
                              "videoDuration": 10,                  // 视频时长
                              "videoUrl" : "http://itbour-generate.img-cn-hangzhou.aliyuncs.com/video/1.mp4",  // 视频 url
                              "videoThumb" : "http://itbour-generate.img-cn-hangzhou.aliyuncs.com/video/thumb/1.jpg", // 视频缩略图
                            }
     * */
    labUtil.generateProductVideo = function(productId, callback) {
        rpcFunc.createProductVideo(productId, function(error, result){
            if(error) {
                return callback(error, null);
            }
            return callback(error, result);
        })
    };
    /**
     * 创建/修改用户作品
     *
     * @param userId 用户唯一标识
     * @param videoTg 视频提纲
     * @param callback 回调
     *         error: 保存失败
     *         result: {
     *              productId : 136
      *         }
     * */
    labUtil.saveVideoTgInfo_v6_3 = function(userId, videoTg, callback) {
        var userDoc = new VideoUserDocModel({});
        userDoc.user_id = userId;
        userDoc.doc_name = videoTg.productNm || '我的作品';
        userDoc.design_id = videoTg.designId;
        userDoc.tg_data = JSON.stringify(videoTg.coreStructure);
        userDoc.ver = videoTg.coreStructure.version;
        userDoc.update_by = userId;
        // 不管是新建还是修改, 视频相关信息均需要清空
        userDoc.thumb = '';
        userDoc.video = '';
        userDoc.duration = 0;
        // 1. 创建
        if(videoTg.productId <= 0) {
            // 1.1 查询模板信息
            var designEntity = new VideoDesignDocModel({
                design_id : videoTg.design_id,
                del_flg : 0
            });
            designEntity.findFromDB(function(getDesignErr, designs){
                if(getDesignErr || designs.length <= 0) {
                    return callback(getDesignErr || '模板不存在', null)
                }
                // 1.2 提取模板相关信息
                var design = designs[0];
                userDoc.size_id = design.size_id;
                userDoc.type_id = design.type_id;
                // 1.3 保存到数据库
                userDoc.saveToDB(function(insertErr, insertId){
                    if(insertErr) {
                        return callback(insertErr, null);
                    }
                    return callback(null, {productId : insertId})
                });
            });
            return;
        }
        // 2. 修改
        userDoc.doc_id = videoTg.productId;
        userDoc.updateToDB(function(updateErr){
           return callback(updateErr, {productId:videoTg.productId})
        });
    };

    return labUtil;
})();

module.exports = labUtil;